package com.seed.application.validator;

import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.query.QueryColumn;
import com.mybatisflex.core.row.DbChain;
import com.mybatisflex.core.row.Row;
import com.seed.core.column.Column;
import com.seed.core.enumeration.PropertyType;
import com.seed.core.pojo.Const;
import com.seed.core.pojo.seed.BelongsTos;
import com.seed.core.pojo.seed.Seed;
import com.seed.core.query.pojo.Declared;
import com.seed.util.RowKit;
import com.seed.util.ThrowKit;

import java.util.List;
import java.util.Map;

import static com.mybatisflex.core.query.QueryMethods.count;

public class UpdateValidator {

    public static void validate(Seed seed, Map<String, Declared> declareds, List<Row> rows) {
        for (Row row: rows) validate(seed, declareds, row);
    }

    public static void validate(Seed seed, Map<String, Declared> declareds, Row row) {
        for(Map.Entry<String, Declared> entry: declareds.entrySet()) {
            String columnOrCross = entry.getKey();
            if(Const.ID.equals(columnOrCross)) continue;

            Declared value = entry.getValue();
            PropertyType propertyType = value.getType();
            Map<String, Column> columns = seed.getColumns();
            switch (propertyType) {
                case none, asterisk -> {
                    for(Map.Entry<String, Column> e: columns.entrySet()) {
                        String columnName = e.getKey();
                        if(Const.ID.equals(columnName)) continue;

                        validate(seed, e.getValue(), row);
                    }
                }
                case column -> validate(seed, columns.get(columnOrCross), row);
                case belongsTo -> {
                    BelongsTos belongsTo = (BelongsTos) value.getProperty();
                    String columnName = belongsTo.inferSelfColumn();
                    Column column = columns.get(columnName);
                    validate(seed, column, row);
                }
            }
        }
    }

    public static void validate(Seed seed, Column column, Row row) {
        validateRequired(column, row);
        validateLength(column, row);
        validateUnique(seed, column, row);
        validateMaxMin(column, row);
    }

    public static void validateRequired(Column column, Row row) {
        Boolean required = column.getRequired();
        String columnName = column.getName();
        if(required == null || !required) return;

        String fieldName = StrUtil.toCamelCase(columnName);
        Object value = row.get(fieldName);

//        RuntimeException e = new RuntimeException(String.format("【%s】不能为空", column.getLabel()));
//        if(value == null) throw e;
//
//        if(value instanceof String s && StrUtil.isBlank(s)) throw e;
    }

    public static void validateLength(Column column, Row row) {
        SaveValidator.validateLength(column, row);
    }

    public static void validateUnique(Seed seed, Column column, Row row) {
        Boolean unique = column.getUnique();
        if(unique == null || !unique) return;

        String columnName = column.getName();
        String fieldName = StrUtil.toCamelCase(columnName);
        Object value = RowKit.getSelfValue(row, fieldName);
        if(value == null) return;

        Object id = row.get(Const.ID);
        String tableName = seed.getTableName();
        int count = (int) DbChain.table(tableName)
                .select(count())
                .where(new QueryColumn(columnName).eq(value).and(Const.ID + " != ?", id))
                .obj();
        if(count > 0) ThrowKit.exception("%s【%s】已存在", column.getLabel(), value);
    }

    public static void validateMaxMin(Column column, Row row) {
        SaveValidator.validateMaxMin(column, row);
    }
}
